home *** CD-ROM | disk | FTP | other *** search
/ Power CD / Power CD ATARI-Rechner Lieben.iso / ALLERLEI / GOBJ_112 / UNITS / OVALIDAT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-03-27  |  17.4 KB  |  681 lines

  1. {**************************************
  2.  *  O b j e c t G E M   Version 1.12  *
  3.  *  Copyright 1992-94 by Thomas Much  *
  4.  **************************************
  5.  *       Unit  O V A L I D A T        *
  6.  **************************************
  7.  *    Softdesign Computer Software    *
  8.  *    Thomas Much, Gerwigstraße 46,   *
  9.  *  76131 Karlsruhe, (0721) 62 28 41  *
  10.  *         Thomas Much @ KA2          *
  11.  *  UK48@ibm3090.rz.uni-karlsruhe.de  *
  12.  **************************************
  13.  *    erstellt am:        13.07.1992  *
  14.  *    letztes Update am:  03.03.1994  *
  15.  **************************************}
  16.  
  17. {
  18.   WICHTIGE ANMERKUNGEN ZUM QUELLTEXT:
  19.  
  20.   ObjectGEM wird ab sofort mit dem _vollständigen_ Quelltext ausgeliefert,
  21.   d.h. jeder kann sich die Unit selbst compilieren, womit die extrem
  22.   lästigen Kompatibilitätsprobleme mit den PP-Releases beseitigt sind.
  23.   ObjectGEM ist und bleibt aber trotzdem SHAREWARE, d.h. wer die Biblio-
  24.   thek regelmäßig benutzt, muß sich REGISTRIEREN lassen (so wie bisher).
  25.   Im Moment gibt es dafür dann "nur" die neueste Version; eine geTEXte
  26.   Doku ist aber in Arbeit, so daß auch ein gedrucktes Handbuch immer
  27.   wahrscheinlicher wird.
  28.  
  29.   Der Quelltext enthält z.Z. noch _keine_ Kommentare; wer sich dennoch die
  30.   Mühe macht, ihn zu lesen, wird feststellen, daß er außerdem noch recht
  31.   "wirr" und teilweise umständlich geschrieben ist, oder daß er evtl. auch
  32.   unnötige Teile enthält. Das liegt daran, daß dieser Quelltext eigentlich
  33.   gar nicht für eine Veröffentlichung gedacht war, aber immer häufiger auf-
  34.   tretende PP-Updates haben mich schier zur Verzweiflung getrieben...
  35.   Das alles sollte aber kein Grund sein, ObjectGEM nicht einzusetzen, denn
  36.   sobald nach "außen" die von mir gewünschte Funktionalität erreicht ist
  37.   (d.h. wenn alle wichtigen Objekte vorhanden sind, z.B. TEditWindow etc.),
  38.   werde ich mich um die "innere" Optimierung kümmern (dazu gehören dann
  39.   auch die Kommentare). Die bisher geschriebenen ObjectGEM-Anwendungen
  40.   können dann natürlich weiterverwendet werden.
  41.  
  42.   Wer beim Durchstöbern des Textes auf vermeintliche Fehler oder verbesse-
  43.   rungswürdige Stellen trifft (von letzterem gibt es sicherlich noch viele),
  44.   kann mir dies gerne mitteilen - ich habe auch ich nichts gegen kostenlos
  45.   zur Verfügung gestellte optimierte Routinen (sofern sich jemand die Mühe
  46.   macht). Wer in anderen Projekten, die nicht in direkter Konkurrenz zu
  47.   ObjectGEM stehen, einzelne Routinen verwenden möchte, wendet sich bitte
  48.   an mich (ein solcher Austausch sollte kein Problem sein).
  49.  
  50.   Wer sich auf nicht dokumentierte "implementation"- oder "private"-Eigen-
  51.   schaften verläßt, darf sich nicht über Inkompatibilitäten zu späteren
  52.   Versionen wundern; wer meint, eine Dokumentationslücke entdeckt zu haben
  53.   (außer dem "Abgrund" des noch fehlenden Handbuchs...), kann mir dies
  54.   gerne mitteilen.
  55.  
  56.   WICHTIG: Wer den Quelltext verändert und dann Probleme beim Compilieren,
  57.   Ausführen o.ä. hat, kann nicht damit rechnen, daß ich den Fehler suche;
  58.   tritt der Fehler allerdings auch mit dem Original-Quelltext auf, würde
  59.   ich mich über eine genaue Fehlerbeschreibung freuen. Veränderte Quell-
  60.   texte dürfen _nicht_ weitergegeben werden, dies wäre ein Verstoß gegen
  61.   das Copyright!
  62.  
  63.   Kleine Info zum Schluß: Als "default tabsize" verwende ich 2. Wer drei
  64.   Punkte ("...") im Quelltext entdeckt, hat eine Stelle gefunden, an der
  65.   ich z.Z. arbeite ;-)
  66.  
  67.   "Möge die OOP mit Euch sein!"
  68. }
  69.  
  70.  
  71. {$IFDEF DEBUG}
  72.     {$B+,D+,G-,I-,L+,N-,P-,Q+,R+,S+,T-,V-,X+,Z+}
  73. {$ELSE}
  74.     {$B+,D-,G-,I-,L-,N-,P-,Q-,R-,S-,T-,V-,X+,Z+}
  75. {$ENDIF}
  76.  
  77. unit OValidat;
  78.  
  79. interface
  80.  
  81. uses
  82.  
  83.     Objects,OTypes,OWindows;
  84.  
  85. type
  86.  
  87.     PFilterValidator       = ^TFilterValidator;
  88.     TFilterValidator       = object(TValidator)
  89.         public
  90.         ValidChars: TCharSet;
  91.         constructor Init(ValidCharSet: TCharSet);
  92.         procedure Error; virtual;
  93.         function IsValid(s: string): boolean; virtual;
  94.         function IsValidInput(var s: string; SuppressFill: boolean): boolean; virtual;
  95.     end;
  96.  
  97.     PRangeValidator        = ^TRangeValidator;
  98.     TRangeValidator        = object(TFilterValidator)
  99.         public
  100.         Min,
  101.         Max: longint;
  102.         constructor Init(AMin,AMax: longint);
  103.         procedure Error; virtual;
  104.         function IsValid(s: string): boolean; virtual;
  105.         function IsValidInput(var s: string; SuppressFill: boolean): boolean; virtual;
  106.     end;
  107.  
  108.     PLookupValidator       = ^TLookupValidator;
  109.     TLookupValidator       = object(TValidator)
  110.         public
  111.         function IsValid(s: string): boolean; virtual;
  112.         function Lookup(s: string): boolean; virtual;
  113.     end;
  114.  
  115.     PStringLookupValidator = ^TStringLookupValidator;
  116.     TStringLookupValidator = object(TLookupValidator)
  117.         public
  118.         Strings: PStringCollection;
  119.         constructor Init(AString: PStringCollection);
  120.         destructor Done; virtual;
  121.         procedure Error; virtual;
  122.         function Lookup(s: string): boolean; virtual;
  123.         procedure NewStringList(AString: PStringCollection); virtual;
  124.     end;
  125.  
  126.     PPXPictureValidator    = ^TPXPictureValidator;
  127.     TPXPictureValidator    = object(TValidator)
  128.         public
  129.         Pic: PString;
  130.         constructor Init(APic: string; AutoFill: boolean);
  131.         destructor Done; virtual;
  132.         procedure Error; virtual;
  133.         function IsValid(s: string): boolean; virtual;
  134.         function IsValidInput(var s: string; SuppressFill: boolean): boolean; virtual;
  135.         function Picture(var Input: string; AutoFill: boolean): TPicResult; virtual;
  136.     end;
  137.  
  138.  
  139.  
  140. implementation
  141.  
  142. uses
  143.  
  144.     OProcs;
  145.  
  146.  
  147. { *** Objekt TFILTERVALIDATOR *** }
  148.  
  149. constructor TFilterValidator.Init(ValidCharSet: TCharSet);
  150.  
  151.     begin
  152.         if not(inherited Init) then fail;
  153.         Options:=voOnEdit;
  154.         ValidChars:=ValidCharSet
  155.     end;
  156.  
  157.  
  158. procedure TFilterValidator.Error;
  159.  
  160.     begin
  161.         if Application<>nil then
  162.             with Application^ do
  163.                 begin
  164.                     if (Attr.Country=FRG) or (Attr.Country=SWG) then
  165.                         Alert(Window,1,NOTE,'Die Eingabe enthält ungültige Zeichen.','  &OK  ')
  166.                     else
  167.                         Alert(Window,1,NOTE,'Invalid characters in input.','  &OK  ')
  168.                 end
  169.     end;
  170.  
  171.  
  172. function TFilterValidator.IsValid(s: string): boolean;
  173.     var q  : integer;
  174.         vld: boolean;
  175.  
  176.     begin
  177.         vld:=inherited IsValid(s);
  178.         if vld then
  179.             for q:=1 to length(s) do
  180.                 if not(s[q] in ValidChars) then vld:=false;
  181.         IsValid:=vld
  182.     end;
  183.  
  184.  
  185. function TFilterValidator.IsValidInput(var s: string; SuppressFill: boolean): boolean;
  186.     var q: integer;
  187.  
  188.     begin
  189.         IsValidInput:=true;
  190.         if length(s)>0 then
  191.             for q:=1 to length(s) do
  192.                 if not(s[q] in ValidChars) then
  193.                     begin
  194.                         if upcase(s[q]) in ValidChars then s[q]:=upcase(s[q])
  195.                         else
  196.                             IsValidInput:=false
  197.                     end
  198.     end;
  199.  
  200. { *** TFILTERVALIDATOR *** }
  201.  
  202.  
  203.  
  204. { *** Objekt TRANGEVALIDATOR *** }
  205.  
  206. constructor TRangeValidator.Init(AMin,AMax: longint);
  207.  
  208.     begin
  209.         if not(inherited Init(['0'..'9','+','-'])) then fail;
  210.         Options:=Options and not(voOnEdit);
  211.         Min:=AMin;
  212.         Max:=AMax;
  213.         if Min>=0 then ValidChars:=ValidChars-['-']
  214.     end;
  215.  
  216.  
  217. procedure TRangeValidator.Error;
  218.  
  219.     begin
  220.         if Application<>nil then
  221.             with Application^ do
  222.                 begin
  223.                     if (Attr.Country=FRG) or (Attr.Country=SWG) then
  224.                         Alert(Window,1,NOTE,' Wert ist nicht im Bereich | von '+ltoa(Min)+' bis '+ltoa(Max)+'.','  &OK  ')
  225.                     else
  226.                         Alert(Window,1,NOTE,' Value is not in the range | '+ltoa(Min)+' to '+ltoa(Max)+'.','  &OK  ')
  227.             end
  228.     end;
  229.  
  230.  
  231. function TRangeValidator.IsValid(s: string): boolean;
  232.     var value: longint;
  233.  
  234.     begin
  235.         if inherited IsValid(s) then
  236.             begin
  237.                 value:=atol(s);
  238.                 IsValid:=(value>=Min) and (value<=Max)
  239.             end
  240.         else
  241.             IsValid:=false
  242.     end;
  243.  
  244.  
  245. function TRangeValidator.IsValidInput(var s: string; SuppressFill: boolean): boolean;
  246.     var value: longint;
  247.  
  248.     begin
  249.         if inherited IsValidInput(s,SuppressFill) then
  250.             begin
  251.                 value:=atol(s);
  252.                 IsValidInput:=(value>=Min) and (value<=Max)
  253.             end
  254.         else
  255.             IsValidInput:=false
  256.     end;
  257.  
  258. { *** TRANGEVALIDATOR *** }
  259.  
  260.  
  261.  
  262. { *** Objekt TLOOKUPVALIDATOR *** }
  263.  
  264. function TLookupValidator.IsValid(s: string): boolean;
  265.     var vald: boolean;
  266.  
  267.     begin
  268.         vald:=Lookup(s);
  269.         if vald then
  270.             if bTst(Options,voNotEmpty) then
  271.                 vald:=length(s)>0;
  272.         IsValid:=vald
  273.     end;
  274.  
  275.  
  276. function TLookupValidator.Lookup(s: string): boolean;
  277.  
  278.     begin
  279.         Lookup:=true
  280.     end;
  281.  
  282. { *** TLOOKUPVALIDATOR *** }
  283.  
  284.  
  285.  
  286. { *** Objekt TSTRINGLOOKUPVALIDATOR *** }
  287.  
  288. constructor TStringLookupValidator.Init(AString: PStringCollection);
  289.  
  290.     begin
  291.         if not(inherited Init) then fail;
  292.         Strings:=AString
  293.     end;
  294.  
  295.  
  296. destructor TStringLookupValidator.Done;
  297.  
  298.     begin
  299.         NewStringList(nil);
  300.         inherited Done
  301.     end;
  302.  
  303.  
  304. procedure TStringLookupValidator.Error;
  305.  
  306.     begin
  307.         if Application<>nil then
  308.             with Application^ do
  309.                 begin
  310.                     if (Attr.Country=FRG) or (Attr.Country=SWG) then
  311.                         Alert(Window,1,NOTE,'Die Eingabe ist nicht gültig.','  &OK  ')
  312.                     else
  313.                         Alert(Window,1,NOTE,'Input not in valid-list.','  &OK  ')
  314.             end
  315.     end;
  316.  
  317.  
  318. function TStringLookupValidator.Lookup(s: string): boolean;
  319.     var dummy: longint;
  320.  
  321.     begin
  322.         if Strings<>nil then Lookup:=Strings^.Search(@s,dummy)
  323.         else
  324.             Lookup:=false
  325.     end;
  326.  
  327.  
  328. procedure TStringLookupValidator.NewStringList(AString: PStringCollection);
  329.  
  330.     begin
  331.         if Strings<>nil then Dispose(Strings,Done);
  332.         Strings:=AString
  333.     end;
  334.  
  335. { *** TSTRINGLOOKUPVALIDATOR *** }
  336.  
  337.  
  338.  
  339. { *** Objekt TPXPICTUREVALIDATOR *** }
  340.  
  341. constructor TPXPictureValidator.Init(APic: string; AutoFill: boolean);
  342.     var dummy: string;
  343.  
  344.     begin
  345.         inherited Init;
  346.         Pic:=NewStr(APic);
  347.         Options:=voOnAppend;
  348.         if AutoFill then Options:=Options or voFill;
  349.         dummy:='';
  350.         if Picture(dummy,false)<>prEmpty then Status:=vsSyntax
  351.     end;
  352.  
  353.  
  354. destructor TPXPictureValidator.Done;
  355.  
  356.     begin
  357.         DisposeStr(Pic);
  358.         inherited Done
  359.     end;
  360.  
  361.  
  362. procedure TPXPictureValidator.Error;
  363.  
  364.     begin
  365.         if Application<>nil then
  366.             with Application^ do
  367.                 begin
  368.                     if (Attr.Country=FRG) or (Attr.Country=SWG) then
  369.                         Alert(Window,1,NOTE,'Die Eingabe paßt nicht auf|'+Pic^,'  &OK  ')
  370.                     else
  371.                         Alert(Window,1,NOTE,'Input does not conform to|'+Pic^,'  &OK  ')
  372.             end
  373.     end;
  374.  
  375.  
  376. function TPXPictureValidator.IsValid(s: string): boolean;
  377.     var res: TPicResult;
  378.  
  379.     begin
  380.         res:=Picture(s,false);
  381.         if bTst(Options,voNotEmpty) and ((res=prEmpty) or (length(s)=0)) then
  382.             begin
  383.                 IsValid:=false;
  384.                 exit
  385.             end;
  386.         IsValid:=(Pic=nil) or (res=prComplete) or (res=prEmpty)
  387.     end;
  388.  
  389.  
  390. function TPXPictureValidator.IsValidInput(var s: string; SuppressFill: boolean): boolean;
  391.  
  392.     begin
  393.         IsValidInput:=(Pic=nil) or (Picture(s,bTst(Options,voFill) and not(SuppressFill))<>prError)
  394.     end;
  395.  
  396.  
  397. function TPXPictureValidator.Picture(var Input: string; AutoFill: boolean): TPicResult;
  398.     const special: set of char = [';','*','[',']','{','}',','];
  399.  
  400.     var q,k1,k2,mip: integer;
  401.         outp       : string;
  402.         ret        : TPicResult;
  403.  
  404.     function check(inpt,mask: string; var out: string): TPicResult;
  405.         label _getph;
  406.  
  407.         var ph,aus             : string;
  408.             c,d,ip,mp,bis,letzt: integer;
  409.             gueltig            : boolean;
  410.             cnt                : longint;
  411.             r                  : TPicResult;
  412.  
  413.         begin
  414.             { Ausfüllen verhindern + AutoFill beachten... }
  415.             k2:=0;
  416.             c:=1;
  417.             while c<=length(mask) do
  418.                 begin
  419.                     case mask[c] of
  420.                         ';': inc(c);
  421.                         '[': inc(k2);
  422.                         ']': dec(k2)
  423.                     end;
  424.                     inc(c)
  425.                 end;
  426.             if k2<>0 then
  427.                 begin
  428.                     check:=prSyntax;
  429.                     exit
  430.                 end
  431.             else
  432.                 check:=prIncomplete;
  433.             aus:=out;
  434.             mp:=1;
  435.             ip:=1;
  436.             while mp<=length(mask) do
  437.                 begin
  438.                     case mask[mp] of
  439.                         '}',']': begin
  440.                                              check:=prAmbiguous;
  441.                                              exit
  442.                                      end;
  443.                         ',': begin
  444.                                      check:=prSyntax;
  445.                                      exit
  446.                              end;
  447.                         ';': begin
  448.                                      ph:=mask[mp+1];
  449.                                      inc(mp,2);
  450.                                      goto _getph
  451.                                  end;
  452.                         '*': begin
  453.                                c:=mp+1;
  454.                                cnt:=0;
  455.                                while mask[c] in ['0'..'9'] do
  456.                                  begin
  457.                                    cnt:=cnt*10+ord(mask[c])-48;
  458.                                    inc(c)
  459.                                  end;
  460.                                mp:=c;
  461.                                inc(c);
  462.                                letzt:=mp;
  463.                                case mask[mp] of
  464.                                  '[': begin
  465.                                         check:=prSyntax;
  466.                                         exit
  467.                                       end;
  468.                                  '{': begin
  469.                                         bis:=1;
  470.                                                         while bis>0 do
  471.                                                             begin
  472.                                                                 case mask[c] of
  473.                                                                   ';': inc(c);
  474.                                                                     '{': inc(bis);
  475.                                                                     '}': dec(bis)
  476.                                                                 end;
  477.                                                                 inc(c)
  478.                                                             end;
  479.                                                         letzt:=c-1
  480.                                                     end
  481.                                end;
  482.                                if (letzt=mp) or (letzt-mp>1) then
  483.                                  begin
  484.                                        if cnt=0 then
  485.                                          repeat
  486.                                                      r:=check(StrPRight(inpt,length(inpt)+1-ip),copy(mask,mp,letzt+1-mp),aus);
  487.                                                      if r=prComplete then inc(ip,mip-1)
  488.                                          until r<>prComplete
  489.                                        else
  490.                                          for d:=1 to cnt do
  491.                                                      if check(StrPRight(inpt,length(inpt)+1-ip),copy(mask,mp,letzt+1-mp),aus)=prComplete then
  492.                                                        inc(ip,mip-1)
  493.                                            else
  494.                                              begin
  495.                                                check:=prError;
  496.                                                exit
  497.                                                  end
  498.                                    end;
  499.                                      mp:=c
  500.                                  end;
  501.                         '[': begin
  502.                                      c:=mp+1;
  503.                                      bis:=1;
  504.                                      while bis>0 do
  505.                                          begin
  506.                                              case mask[c] of
  507.                                                ';': inc(c);
  508.                                                  '[': inc(bis);
  509.                                                  ']': dec(bis)
  510.                                              end;
  511.                                              inc(c)
  512.                                          end;
  513.                                      if c-mp>2 then
  514.                                          if check(StrPRight(inpt,length(inpt)+1-ip),copy(mask,mp+1,c-mp-2),aus)=prComplete then
  515.                                            inc(ip,mip-1);
  516.                                      mp:=c
  517.                              end;
  518.                         '{': begin
  519.                                      c:=mp+1;
  520.                                      bis:=1;
  521.                                      while bis>0 do
  522.                                          begin
  523.                                              case mask[c] of
  524.                                                ';': inc(c);
  525.                                                  '{': inc(bis);
  526.                                                  '}': dec(bis)
  527.                                              end;
  528.                                              inc(c)
  529.                                          end;
  530.                                      d:=mp+1;
  531.                                      letzt:=d;
  532.                                      bis:=1;
  533.                                      gueltig:=false;
  534.                                      while (bis>0) and not(gueltig) do
  535.                                        begin
  536.                                              case mask[d] of
  537.                                                ';': inc(d);
  538.                                                  '{': inc(bis);
  539.                                                  '}': dec(bis);
  540.                                                  ',': if bis=1 then
  541.                                                         if d-letzt>0 then
  542.                                                             begin
  543.                                                               if check(StrPRight(inpt,length(inpt)+1-ip),copy(mask,letzt,d-letzt),aus)=prComplete then
  544.                                                                 begin
  545.                                                                     inc(ip,mip-1);
  546.                                                                   gueltig:=true
  547.                                                                 end;
  548.                                                               letzt:=d+1
  549.                                                             end
  550.                                              end;
  551.                                              inc(d)
  552.                                        end;
  553.                                      if not(gueltig) then
  554.                                          if d-letzt>1 then
  555.                                          begin
  556.                                                  if check(StrPRight(inpt,length(inpt)+1-ip),copy(mask,letzt,d-letzt-1),aus)=prComplete then
  557.                                                    inc(ip,mip-1)
  558.                                        else
  559.                                          begin
  560.                                            check:=prError;
  561.                                            exit
  562.                                              end
  563.                                          end;
  564.                                      mp:=c
  565.                              end
  566.                     else
  567.                         begin
  568.                             ph:='';
  569.                             _getph:
  570.                             while not(mask[mp] in special) and (mp<=length(mask)) do
  571.                                 begin
  572.                                     ph:=ph+mask[mp];
  573.                                     inc(mp)
  574.                                 end;
  575.                             if length(inpt)+1-ip<length(ph) then bis:=length(inpt)-ip
  576.                             else
  577.                                 bis:=length(ph)-1;
  578.                             for c:=0 to bis do
  579.                                 begin
  580.                                     case ph[c+1] of
  581.                                         '#': if not(inpt[ip+c] in ['0'..'9']) then
  582.                                                    begin
  583.                                                          check:=prError;
  584.                                                          exit
  585.                                                    end
  586.                                                  else
  587.                                                      aus:=aus+inpt[ip+c];
  588.                                         '?': if not(UpChar(inpt[ip+c]) in ['A'..'Z','Ä','Ö','Ü']) then
  589.                                                      begin
  590.                                                          check:=prError;
  591.                                                          exit
  592.                                                      end
  593.                                                  else
  594.                                                      aus:=aus+inpt[ip+c];
  595.                                         '&': if not(UpChar(inpt[ip+c]) in ['A'..'Z','Ä','Ö','Ü']) then
  596.                                                      begin
  597.                                                          check:=prError;
  598.                                                          exit
  599.                                                      end
  600.                                                  else
  601.                                                      aus:=aus+UpChar(inpt[ip+c]);
  602.                                         '@': aus:=aus+inpt[ip+c];
  603.                                         '!': aus:=aus+UpChar(inpt[ip+c])
  604.                                     else
  605.                                         begin
  606.                                             if UpChar(ph[c+1])=UpChar(inpt[ip+c]) then aus:=aus+ph[c+1]
  607.                                             else
  608.                                                 begin
  609.                                                     check:=prError;
  610.                                                     exit
  611.                                                 end
  612.                                         end
  613.                                     end
  614.                                 end;
  615.                             if bis<length(ph)-1 then exit;
  616.                             inc(ip,bis+1)
  617.                         end
  618.                     end
  619.                 end;
  620.             mip:=ip;
  621.             out:=aus;
  622.             check:=prComplete
  623.         end;
  624.  
  625.     begin
  626.         if Pic=nil then
  627.             begin
  628.                 Picture:=prError;
  629.                 exit
  630.             end;
  631.         Picture:=prSyntax;
  632.         q:=length(Pic^);
  633.         if (q=0) or (q>253) then exit;
  634.         k1:=0;
  635.         while (Pic^[q]=';') and (q>0) do
  636.             begin
  637.                 inc(k1);
  638.                 dec(q)
  639.             end;
  640.         if odd(k1) then exit;
  641.         if StrPRight(Pic^,1)='*' then
  642.             begin
  643.                 q:=length(pic^)-1;
  644.                 k1:=0;
  645.                 while (Pic^[q]=';') and (q>0) do
  646.                     begin
  647.                         inc(k1);
  648.                         dec(q)
  649.                     end;
  650.                 if not(odd(k1)) then exit
  651.             end;
  652.         q:=1;
  653.         k1:=0;
  654.         k2:=0;
  655.         while q<=length(Pic^) do
  656.             begin
  657.                 case Pic^[q] of
  658.                     ';': inc(q);
  659.                     '{': inc(k1);
  660.                     '}': dec(k1);
  661.                     '[': inc(k2);
  662.                     ']': dec(k2)
  663.                 end;
  664.                 inc(q)
  665.             end;
  666.         if (k1<>0) or (k2<>0) then exit;
  667.         if length(Input)=0 then
  668.             begin
  669.                 Picture:=prEmpty;
  670.                 exit
  671.             end;
  672.         outp:='';
  673.         ret:=check(Input,'{'+Pic^+'}',outp);
  674.         if mip<=length(Input) then ret:=prAmbiguous;
  675.         if (ret=prComplete) or (ret=prIncomplete) then Input:=outp;
  676.         Picture:=ret
  677.     end;
  678.  
  679. { *** Objekt TPXPICTUREVALIDATOR *** }
  680.  
  681. end.